
using System;
using System.Threading;

namespace Xeralabs.Core.Utils.Internals
{
    public enum TaskType
    {
        TASK_TIME,
        TASK_FRAME,
        TASK_IDLE,
        TASK_END_FRAME
    }
    public enum TaskState
    {
        TASK_ACTIVE,
        TASK_PAUSE,
        TASK_DELETE,
        TASK_POOL
    }

    public class TaskInfo
    {
        public iTask Task;
        public TaskInfo NextTask;
        public TaskState Status;
        public int Id;
        public object UserData;

        public double StartTime;
        public double Rate;
        public double EndTime;
        public double ElapsedTime;
        public double LastTime;
        public double NextTime;
        public double Budget;
        public double TaskOverhead;

        public TaskInfo()
        {
            this.Clear();
        }

        internal void Clear()
        {
            this.Task = null;
            this.NextTask = null;
            this.Status = TaskState.TASK_POOL;
            this.Id = -1;
            this.UserData = null;

            this.StartTime = 0.0;
            this.Rate = 0.0;
            this.EndTime = 0.0;
            this.ElapsedTime = 0.0;
            this.LastTime = 0.0;
            this.NextTime = 0.0;
            this.Budget = 0.0;
            this.TaskOverhead = 0.0;
        }
    }

    public class TaskInfoPool  : AbstractPool<TaskInfo>
    {
        public TaskInfoPool()
            : base(1000) { }

        protected override TaskInfo CreateNewPoolObject()
        {
            TaskInfo res = new TaskInfo();
            GC.SuppressFinalize(res);
            return res;
        }

        public override void ReleaseObject(TaskInfo obj)
        {
            obj.Clear();
            base.ReleaseObject(obj);
        }
        public override void Dispose()
        {
            lock (Pool)
            {
                while (NumObjects > Pool.Count)
                    Monitor.Wait(Pool);

                // El truco de las iteraciones cuadruples
                int maxIte = Pool.Count / 4;
                maxIte *= 4;

                for (int a = 0; a < maxIte; a += 4)
                {
                    GC.ReRegisterForFinalize(Pool[a]);
                    GC.ReRegisterForFinalize(Pool[a + 1]);
                    GC.ReRegisterForFinalize(Pool[a + 2]);
                    GC.ReRegisterForFinalize(Pool[a + 3]);
                }
                for (int b = maxIte; b < Pool.Count; b++)
                {
                    GC.ReRegisterForFinalize(Pool[b]);
                }
                // El truco de las iteraciones cuadruples
            }
        }
    }
}
